#include "tm1638.h"
#include "FreeRTOS.h"
#include "task.h"
#include "delay.h"

TM1638_TypeDef tm1638;

u8 DispTab[4];
u8 KeyValue[4];        //保存按键值
u8 Update_disp_flg=0;  //更新显示标志

void TM1638_Write(TM1638_TypeDef *TM1638,u8 DATA) //写数据函数
{
   
   u8 i;
   TM1638_DIO_OUT(TM1638);
   for(i=0;i<8;i++)
   {
     TM1638_CLK(TM1638,0);
     delay_us(1);
     if(DATA&0X01)
     {
       TM1638_DIO_DataOUT(TM1638,1);
     }
     else
     {
       TM1638_DIO_DataOUT(TM1638,0);
     }
     DATA>>=1;
     TM1638_CLK(TM1638,1);
     delay_us(1);
   }
}

u8 TM1638_Read(TM1638_TypeDef *TM1638) //读数据函数
{
  u8 i;
  u8 temp=0;
	taskENTER_CRITICAL();           //进入临界区
  TM1638_DIO_IN(TM1638);
  for(i=0;i<8;i++)
  {
    temp>>=1;
    TM1638_CLK(TM1638,0);
    delay_us(1);
    if(TM1638_DIO_DataIN(TM1638)==1)
    {
      temp|=0x80;
    }
    TM1638_CLK(TM1638,1);
    delay_us(1);
  }
	taskEXIT_CRITICAL();            //退出临界区
  return temp;
}

void Write_COM(TM1638_TypeDef *TM1638,u8 cmd) //发送命令字
{
  TM1638_STB(TM1638,0);
  TM1638_Write(TM1638,cmd);
  TM1638_STB(TM1638,1);
}

void Read_key(TM1638_TypeDef *TM1638,u8 *KeyValue)
{
     u8 i;
     TM1638_STB(TM1638,0);
     TM1638_Write(TM1638,0x42);           //读键扫数据 命令 
     delay_us(10);
     for(i=0;i<4;i++) 
         KeyValue[i]=TM1638_Read(TM1638);//4个字节数据合成一个字节 
     TM1638_STB(TM1638,1);           
}

void Write_DATA(TM1638_TypeDef *TM1638,u8 add,u8 DATA) //指定地址写入数据
{
     Write_COM(TM1638,0x44);      //固定地址
     TM1638_STB(TM1638,0);
     TM1638_Write(TM1638,0xc0|add);
     TM1638_Write(TM1638,DATA);
     TM1638_STB(TM1638,1);
}

//数据保存到显示缓冲区
void display(u8 dig,u8 dat)
{
  DispTab[dig]=dat;
}

//显示LED
void display_led(TM1638_TypeDef *TM1638,u8 dig,u8 dat)
{
  Write_DATA(TM1638,dig,dat);
}

u8 Temp[15];
//dig数码管位，seg数码管段，onoff数码管亮灭

void Digital_led(TM1638_TypeDef *TM1638,u8 dig,u16 seg,u8 onoff)
{
	taskENTER_CRITICAL();           //进入临界区
	if(seg==SEG(9)||seg==SEG(10)){
		seg = seg>>8;
		dig++;
	}
  if(onoff)Temp[dig]|=seg;
  else     Temp[dig]&=(~seg);
  Write_DATA(TM1638,(0xc0|dig),Temp[dig]);
	taskEXIT_CRITICAL();             //退出临界区
}

void Digital_led_reg(TM1638_TypeDef *TM1638,u8 dig,u16 seg,u8 onoff)
{
	taskENTER_CRITICAL();           //进入临界区

  if(onoff)Temp[dig]|=seg;
  else     Temp[dig]&=(~seg);
  Write_DATA(TM1638,(0xc0|dig),Temp[dig]);
	taskEXIT_CRITICAL();             //退出临界区
}


//闪烁
void Flicker(TM1638_TypeDef *TM1638,uint8_t n)
{
  u8 i;
  for(i=0;i<n;i++)
  {
    display_led(TM1638,TM1638_GRID1+i*2,0x00);
  }
}


//清除数码管显示
void dispclear(TM1638_TypeDef *TM1638,u8 n,u8 m)
{
  u8 i;
  if(m)
  {
     for(i=0;i<n;i++)
     {
     	DispTab[i]=0x00;
     	display_led(TM1638,TM1638_GRID1+2*i+1,DispTab[i]);
     }
  }
  else
  {
     n = 4 - n;
     for (i=4; i>n; i--)
     {
     	DispTab[i-1]=0x00;
     	display_led(TM1638,TM1638_GRID1+2*i+1,DispTab[i]);
     }		
  }
}

void UpdateDisp(TM1638_TypeDef *TM1638)    //更新四段数码管显示
{
  u8 i;
  for(i=0;i<4;i++)
  {
    display_led(TM1638,TM1638_GRID1+i*2,DispTab[i]);
  }   
}



 //TM1638初始化函数
void TM1638_Init(TM1638_TypeDef *TM1638)
{
	u8 i;
	gpio_init(TM1638->STB_GPIOx,TM1638->STB_PIN_x,GPIO_Mode_Out_PP);
	gpio_init(TM1638->DIO_GPIOx,TM1638->DIO_PIN_x,GPIO_Mode_Out_PP);
	gpio_init(TM1638->CLK_GPIOx,TM1638->CLK_PIN_x,GPIO_Mode_Out_PP);

	Write_COM(TM1638,0x8a);       //亮度 (0x88-0x8f)8级亮度可调
	Write_COM(TM1638,0x40);       //采用地址自动加1
	TM1638_STB(TM1638,0);          
	TM1638_Write(TM1638,0xc0);    //设置起始地址
	for(i=0;i<16;i++)      //传送16个字节的数据
	{
		TM1638_Write(TM1638,0x00);
	}
	TM1638_STB(TM1638,1);

}





